# 自省机制
class Test:
    pass

t = Test()
print(type(t))  # <class '__main__.Test'>

print("=" * 50)
# 检查对象是否是某个类的实例
class Animal:
    pass
class Dog(Animal):
    pass
d = Dog()
print(isinstance(d,Dog))        # True
print(isinstance(d,Animal))    # True
print(isinstance(d,object))     # True

print("=" * 50)
# 列出对象中的所有属性和方法
class MyClass:
    def __init__(self):
        self.x = 10
        self.y = 20

    def my_method(self):
        pass

    def __dir__(self):
        return ['x', 'y', 'my_method']

obj = MyClass()
# 现面会更出示所有属性和方法
# 如果我们在类中定义了__dir__()方法，那么Python解释器会调用这个方法来获取对象中的所有属性和方法
print(dir(obj))

print("=" * 50)
# 检查和获取对象属性
class Person:
    name = "张三"
    age = 30

p = Person()
# 检查属性
print(hasattr(p,"name"))    # True
print(hasattr(p,"age"))     # True
print(hasattr(p,"sex"))     # False
# 获取属性
print(getattr(p,"name"))    # 张三
print(getattr(p,"age"))     # 30
# 获取属性，如果属性不存在，那么返回指定的默认值：“不存在”
print(getattr(p,"sex","不存在"))   # 不存在


# 设置属性
setattr(p,"name","张三丰")
setattr(p,"sex","男")
print(p.sex)    # 男
print(p.name)   # 张三丰
# 删除属性
delattr(p,"sex")
# 由于对象本身就没有gender属性，要删除这个属性会抛出异常 AttributeError: 'Person' object has no attribute 'gender'
# delattr(p,"gender")

print("=" * 50)
# 动态调用对象的方法
class Claculator:
    def add(self, a, b):
        return a + b
    def sub(self, a, b):
        return a - b

calc = Claculator()
# 使用getattr获取方法并调用
add_method = getattr(calc, "add")
print(add_method(10, 5))    # 15

print("=" * 50)
# 获取对象内部状态
class Student:
    def __init__(self, name, age):
        self.name = name
        self.age = age

obj = Student("张三", 18)
print(vars(obj))    # {'name': '张三', 'age': 18}
print(obj.__dict__) # {'name': '张三', 'age': 18}